/*!
 * jQuery gzoom 0.2
 *
 * 2009 Giovanni Battista Lenoci <gianiaz@gianiaz.net>
 *
 * v.0.2 - (17/07/2013) Added setZoom method, now you can set the zoom programmatically
 *
 * Based on minizoomPan plugin of Gian Carlo Mingati Version: 1.0 (18-JUNE-2009) http://www.gcmingati.net/wordpress/wp-content/lab/jquery/minizoompan/
 * Inspiration from jquery lightbox plugin http://leandrovieira.com/projects/jquery/lightbox/
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Requires:
 * jQuery v1.3.2 or later
 * jQuery ui.core.js v.1.7.1
 * jQuery ui.slider.js v.1.7.1
 *
 */
jQuery.fn.gzoom = function(settings) {
  settings = jQuery.extend({
    sW: 10, // small image width
    sH: 10, // small image height
    lW: 20, // large image width
    lH: 20, // large image height
    step : 5,
    frameColor: "#cecece",
    frameWidth: 1,
    re : /thumbs\//,
    replace : '',
    debug : false,
    overlayBgColor : '#000',
    overlayOpacity:0.8,
    containerBorderSize: 10,
    containerResizeSpeed : 400,
    loaderContent: "loading...",  // plain text or an image tag eg.: "<img src='yoursite.com/spinner.gif' />"
    lightbox: false,
    zoomIcon : "" // icon url, if not empty shown on the right-top corner of the image
  }, settings);

  var $slider;

  this.each(function(){

    var swapped = false;

    var $div = jQuery(this).css({width: settings.sW, height: settings.sH, border: settings.frameWidth+"px solid "+settings.frameColor, overflow:'hidden'}).addClass("minizoompan");
    $div.wrap('<div class="gzoomwrap"></div>').css({ width:settings.sW });
    var ig = $div.children().css({position: "relative"});

    jQuery(window).bind("load", function() {
      ig.width(settings.sW);
      ig.height(settings.sH);
    });


    //jQuery("<span class='loader'>"+settings.loaderContent+"<\/span>").insertBefore(ig);
    if(settings.zoomIcon !== '' && settings.lightbox) {
      var $zoom = jQuery('<img class="zoomIcon" src="'+settings.zoomIcon+'" alt="view larger" />').insertBefore(ig);
      $zoom.load(function() {
        $zoom.css({'left':(settings.sW - $zoom.width())+'px'}).show();
      });
      $zoom.click(function() {
        drawIface();
      });
    } else if(settings.lightbox) {
      $div.click(function() {
        drawIface();
      });
      $div.css({'cursor':'pointer'});
    }

    var $plus = jQuery('<div class="ui-icon ui-icon-circle-plus gzoombutton">&nbsp;</div>').insertAfter($div);
    $slider = jQuery('<div class="gzoomSlider" style="display:none"></div>').insertAfter($div).css({ width:(settings.sW-42)+'px'});
    var $minus = jQuery('<div class="ui-icon ui-icon-circle-minus gzoombutton">&nbsp;</div>').insertAfter($div);

    $plus.click(function() {
      valore = parseInt($slider.slider('value'), 10) + settings.step;
      $slider.slider('value', valore);
    });

    $minus.click(function() {
      valore = parseInt($slider.slider('value'), 10) - settings.step;
      $slider.slider('value', valore);
    });

    $slider.slider({value:0,
                    min: 0,
                    max: 100,
                    step: settings.step,
                    change: function(event, ui) {

                      if(!swapped) {
                        var hiSrc = ig.attr("src").replace(settings.re, settings.replace);
                        swapImage(ig, hiSrc);
                        $div.children("span.loader").fadeIn(250);
                        swapped = true;
                      }

                      val = ui.value;

                      newWidth = settings.sW+((settings.lW-settings.sW)*val)/100;
                      newHeight = settings.sH+((settings.lH-settings.sH)*val)/100;
                      ig_pos = ig.position();

                      if(settings.debug && typeof(console) != 'undefined') {
                        console.log('new dimensions:'+newWidth+'x'+newHeight);
                      }

                      deltaWidth = ig.width()-settings.sW;
                      leftPos = Math.abs(ig_pos.left);
                      leftFactor = leftPos/deltaWidth;
                      newDeltaWidth = newWidth-settings.sW;
                      newLeft = (leftFactor*newDeltaWidth)*-1;

                      deltaHeight = ig.height()-settings.sH;
                      topPos = Math.abs(ig_pos.top);
                      topFactor = topPos/deltaHeight;
                      newDeltaHeight = newHeight-settings.sH;
                      newTop = (topFactor*newDeltaHeight)*-1;
                      ig.css({ width: newWidth, height: newHeight, left:newLeft, top:newTop});
                    }
                  });
    $('<br style="clear:both" />').insertAfter($plus);

    function swapImage(param, uri){
      param.load(function () {
        $div.children("span.loader").fadeOut(250);
      }).error(function (){
        alert("Image does not exist or its SRC is not correct.");
      }).attr('src', uri);
    }

    $div.mousemove(function(e){
      var divWidth = $div.width();
      var divHeight = $div.height();
      var igW = ig.width();
      var igH = ig.height();
      var dOs = $div.offset();
      var leftPan = (e.pageX - dOs.left) * (divWidth - igW) / (divWidth+settings.frameWidth*2);
      var topPan = (e.pageY - dOs.top) * (divHeight - igH) / (divHeight+settings.frameWidth*2);

      if(settings.debug && typeof(console) != 'undefined') {
        console.log('left:'+leftPan+'|Top:'+topPan);
      }

      ig.css({left: leftPan, top: topPan});
    });

    if(typeof($.event.special.mousewheel) != 'undefined') {
      ig.mousewheel(function(event, delta) {
        if (delta > 0) {
          valore = parseInt($slider.slider('value')) + settings.step;
          $slider.slider('value', valore);
        } else if (delta < 0) {
          valore = parseInt($slider.slider('value')) - settings.step;
          $slider.slider('value', valore);
        }
        return false; // prevent default
      });
    }

    function resize_fx(intImageWidth,intImageHeight) {

      if(settings.debug && typeof(console) != 'undefined') {
        console.log('resize_fx('+intImageWidth+','+intImageHeight+')');
      }

      if(intImageWidth > ($(window).width()*80/100)) {
        imgWidth = $(window).width()*80/100;
        intImageHeight = (imgWidth/intImageWidth)*intImageHeight;
        $('#zoomedimage').css({'width': imgWidth+'px', 'height':intImageHeight});
        if(settings.debug && typeof(console) != 'undefined') {
          console.log('Img dimensions 80% horizontal:'+imgWidth+'x'+intImageHeight);
        }
      } else {
        imgWidth = intImageWidth;
      }

      if(intImageHeight > $(window).height()*80/100) {
        imgHeight = $(window).height()*80/100;
        imgWidth = (imgHeight/intImageHeight)*imgWidth;
        $('#zoomedimage').css({'width': imgWidth+'px', 'height':imgHeight});
        if(settings.debug && typeof(console) != 'undefined') {
          console.log('Img dimensions 80% vertical:'+imgWidth+'x'+imgHeight);
        }
      } else {
        imgHeight = intImageHeight;
      }

      if(settings.debug && typeof(console) != 'undefined') {
        console.log('Img dimensions:'+imgWidth+'x'+imgHeight);
      }

      // Get current width and height
      var intCurrentWidth = $('#imagebox').width();
      var intCurrentHeight = $('#imagebox').height();
      // Get the width and height of the selected image plus the padding
      var intWidth = (imgWidth + (settings.containerBorderSize * 2)); // Plus the imageŽs width and the left and right padding value
      var intHeight = (imgHeight + (settings.containerBorderSize * 2)); // Plus the imageŽs height and the left and right padding value



      // Diferences
      var intDiffW = intCurrentWidth - intWidth;
      var intDiffH = intCurrentHeight - intHeight;
      // Perfomance the effect
      $('#imagebox').animate({ width: intWidth, height: intHeight },settings.containerResizeSpeed,function() { _show_image(); });
      if ( ( intDiffW == 0 ) && ( intDiffH == 0 ) ) {
        if ( $.browser.msie ) {
          ___pause(250);
        } else {
          ___pause(100);
        }
      }
      $('#lboximgdatacontainer').css({ width: imgWidth });
    };

    function drawIface() {

      $('body').append('<div id="gzoomoverlay"></div><div id="gzoomlbox"><div id="imagebox"><div id="gzoom-cont-img"><img id="zoomedimage"><div id="gzoomloading"><a href="#" id="gzoomloadinglink"><img src="images/loading.gif"></a></div></div></div><div id="gzoomlbox-con-imgdata"><div id="lboximgdatacontainer"><div id="gzoomlbox-image-details"><span id="gzoom-image-caption"></span></div></div></div></div>');

      $('#gzoomoverlay').css({
        backgroundColor:  settings.overlayBgColor,
        opacity:      settings.overlayOpacity,
        width:        $(window).width(),
        height:       $(document).height()
      }).fadeIn();

      // Calculate top and left offset for the gzoomlbox div object and show it
      $('#gzoomlbox').css({
        top:  $(window).scrollTop() + ($(window).height() / 10),
        left: $(window).scrollLeft()
      }).show();

      $('#gzoomoverlay,#gzoomlbox').click(function() {
        close();
      });
      // If window was resized, calculate the new overlay dimensions
      $(window).resize(function() {
        $('#gzoomoverlay').css({
          width:    $(window).width(),
          height:   $(window).height()
        });
        // Calculate top and left offset for the jquery-lightbox div object and show it
        $('#gzoomlbox').css({
          top:  $(window).scrollTop() + ($(window).height() / 10),
          left: $(window).scrollLeft()
        });
      });

      _set_image_to_view();
    }

    function _set_image_to_view() { // show the loading
      // Show the loading
      $('#gzoomlbox-con-imgdata').hide();
      $('#zoomedimage').hide();
      $('#gzoomloading').show();
      // Image preload process
      var objImagePreloader = new Image();
      if(!swapped) {
        var hiSrc = ig.attr("src").replace(settings.re, settings.replace);
      } else {
        var hiSrc = ig.attr("src").replace(settings.re, settings.replace);
      }
      objImagePreloader.onload = function() {
        $('#zoomedimage').attr('src',hiSrc);
        resize_fx(objImagePreloader.width,objImagePreloader.height);
      };
      objImagePreloader.src = hiSrc;
    };

    function _show_image() {
      $('#gzoomloading').hide();
      $('#zoomedimage').fadeIn(function() {
        _show_image_data();
      });
    };

    /**
     * Show the image information
     *
     */
    function _show_image_data() {
      $('#lightbox-loading').hide();
      $('#gzoom-image-caption').html(ig.attr('title'));
      $('#gzoomlbox-con-imgdata').slideDown('fast');
    }

    function close() {
      $('#gzoomlbox').remove();
      $('#gzoomoverlay').fadeOut(function() { $('#gzoomoverlay').remove(); });
      $('embed, object, select').css({ 'visibility' : 'visible' });
    }

    function ___pause(ms) {
      var date = new Date();
      curDate = null;
      do { var curDate = new Date(); }
      while ( curDate - date < ms);
    };



  });

  function setSliderValue(zoom) {
    $slider.slider('value', zoom);
  };

  return {
    setZoom : function(zoom) { setSliderValue(zoom) }
  };


};
